package org.lisy.java.lambda;

import java.util.ArrayList;
import java.util.Collections;

public class LambdaOperate {

	public static void main(String[] args) {
		
		/**
		 * 表达式主要特征:
		 * - 可选类型声明：不需要声明参数类型，编译器可以统一识别参数值
		 * - 可选的参数圆括号：一个参数无需定义圆括号，但多个参数需要定义圆括号
		 * - 可选的大括号：如果主体包含了一个语句，就不需要使用大括号
		 * - 可选的返回关键字：如果主体只有一个表达式返回值则编译器会自动返回值，大括号需要指定表达式返回了一个数值。
		 */
		new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();
		
		/**
		 * 方法引用：
		 * - 静态方法引用：类名::方法名(被引用的方法参数列表和函数式接口中抽象方法的参数一致；
		 * 接口的抽象方法没有返回值，引用的方法可以有返回值也可以没有；接口的抽象方法有返回值，引用的方法必须有相同类型的返回值)
		 * - 对象方法引用：对象名::非静态方法名(注意事项与静态方法引用完全一致)
		 * - 构造方法引用：类名::new(被引用的类必须存在一个构造方法与函数式接口的抽象方法参数列表一致)
		 * - 数组构造方法引用：数据类型[ ]::new
		 * - 特定类型的方法引用：类名::非静态方法
		 * - 类中方法调用父类或本类方法引用：this::方法名；super::方法名
		 */
		System.out.println(printString("quote static method", String::valueOf));
		
		ITest testObject = new Person()::goWalking;
		System.out.println(testObject.run("quote object"));
		
		StructureTest testStructure = Person::new;
        System.out.println(testStructure.run("lisy").toString());
        
        ArrTest testArr = String[]::new;
        String[] arr = testArr.run(5);
        System.out.println(arr.length);
        
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "d", "c", "a", "b");
        Collections.sort(list, String::compareToIgnoreCase);
        System.out.println(list);
        
        Person person = new Person();
        person.go();
	}
	
	public static String printString(String str, ITest test) {
		return test.run(str);
    }
}

class Animal {
	public String sleep(String value) {
		System.out.println(" " + value);
		return value;
	}
}

class Person extends Animal {
	
	String name;
	
	public Person() {
		
	}
	
    public Person(String name) {
        this.name = name;
    }
    
    @Override
	public String toString() {
		return "Person [name=" + name + "]";
	}

	public String goWalking(String string) {
        return string.concat(" static method");
    }
	
	public String sleep(String value) {
		System.out.print(value);
		return value;
	}
	
	public void go() {
		ITest t = this::sleep;
        t.run("bed");
        
        ITest t2 = super::sleep;
        t2.run("sleep");
	}
}

@FunctionalInterface
interface ITest {
    public String run(String string);
}

@FunctionalInterface
interface StructureTest {
    public Person run(String string);
}

@FunctionalInterface
interface ArrTest {
	public String[] run(int length);
}
